package org.dromara.xxmj.utils;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.FileUtil;
import com.ijpay.core.kit.PayKit;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.implementation.bind.annotation.RuntimeType;

import org.dromara.xxmj.config.WechatPayConfig;
import org.springframework.stereotype.Repository;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 微信支付工具类
 *
 * @param
 * @Author 王晨沣
 * @Date 2025-05-14 09:15:38 （可以根据需要修改）
 */
@Slf4j
@Repository
public class WechatUtil {


    private static final ConcurrentHashMap<String, RuntimeType.Verifier> verifierMaps = new ConcurrentHashMap<>();


    /**
     * 获取私钥。
     * 证书路径 本地使用如： D:\\微信平台证书工具\\7.9\\apiclient_key.pem
     * 证书路径 线上使用如： /usr/apiclient_key.pem
     * String filename 私钥文件路径  (required)
     * @return 私钥对象
     */
    public static PrivateKey getPrivateKey() throws IOException {
        String content = new String(Files.readAllBytes(Paths.get("D:\\微信平台证书工具\\7.9\\apiclient_key.pem")), "utf-8");
        try {
            String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
                .replace("-----END PRIVATE KEY-----", "")
                .replaceAll("\\s+", "");

            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(
                new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        }
    }


    /**
     * 生成微信支付签名
     *
     * @param params   需要参与签名的参数（不包含 sign 字段）
     * @return         签名结果（32位大写MD5值）
     * @throws Exception
     */
    public static String generateSign(Map<String, String> params) throws Exception {
        // 1. 过滤空值参数并排序
        List<String> keys = new ArrayList<>(params.keySet());
        keys.remove("sign"); // 排除 sign 字段
        Collections.sort(keys); // 按 ASCII 字符顺序排序

        // 2. 拼接 key=value 字符串
        StringBuilder sb = new StringBuilder();
        for (String key : keys) {
            sb.append(key).append("=").append(params.get(key)).append("&");
        }
        sb.append("key=").append(WechatPayConfig.apiV3Key); // 追加 API 密钥

        // 3. MD5 加密
        return md5(sb.toString());
    }

    /**
     * MD5 加密工具方法
     */
    private static String md5(String input) throws Exception {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] digest = md.digest(input.getBytes("UTF-8"));
        StringBuilder sb = new StringBuilder();
        for (byte b : digest) {
            sb.append(String.format("%02x", b & 0xff));
        }
        return sb.toString().toUpperCase(); // 转为大写
    }

    /**
     * 生成签名
     * @param description 描述
     * @param outTradeNo 订单号
     * @param originPrice 优惠券金额
     * @param price 金额(实际金额)
     * @param userIp 用户IP
     *
     * @Author 王晨沣 2307105054
     * @Date 2025-05-27 14:31:50
     */
    public Map<String, Object> requestWxPayParam (String openId,String description, String outTradeNo, Double price, Double originPrice,String merchantID, String userIp){
        Map<String, Object> body = new HashMap<>();
        body.put("appid", WechatPayConfig.APP_ID); //appID
        body.put("mch_id", WechatPayConfig.Mch_ID); //商户号
        body.put("description", description); //商品描述
        body.put("out_trade_no", outTradeNo); //订单号
        body.put("time_expire", WechatUtil.calculateExpireTime()); //最后支付时间  标准格式：yyyy-MM-DDTHH:mm:ss+TIMEZONE
        body.put("notify_url", WechatPayConfig.APP_URL); //支付成功回调地址

        //商品信息
        Map<String, Object> goodDetail = new HashMap<>();
        goodDetail.put("merchant_goods_id", merchantID);
        goodDetail.put("quantity", 1);
        goodDetail.put("unit_price", Convert.toInt(Math.round(price * 100)));
        body.put("goods_detail", goodDetail);

        Map<String, Object> details = new HashMap<>();
        details.put("cost_price", originPrice); //原价
        body.put("detail", details);

        Map<String, Object> amounts = new HashMap<>();
        amounts.put("total", Convert.toInt(Math.round(price * 100)));
        body.put("amount", amounts); //金额信息 订单总金额，单位为分，整型

        Map<String, Object> scene_info = new HashMap<>();
        scene_info.put("payer_client_ip", userIp);
        body.put("scene_info", scene_info);

        Map<String, String> user = new HashMap<>();
        user.put("openid", openId);
        body.put("payer", user);
        return body;
    }

    /**
     * 获取证书序列号
     * @Author 王晨沣 2307105054
     * @Date 2025-05-27 10:55:44
     */
    public String getSerialNumber() {
        //获取证书序列号
        X509Certificate certificate = PayKit.getCertificate(FileUtil.getInputStream(WechatPayConfig.certPath));
        return certificate.getSerialNumber().toString(16).toUpperCase();
    }

//    /**
//     * 获取平台证书列表
//     * @param description 描述
//     * @param outTradeNo 订单号
//     * @param goodsTag 优惠券金额
//     * @param amount 金额(实际金额)
//     * @param userIp 用户IP
//     *
//     * @Author 王晨沣 2307105054
//     * @Date 2025-05-27 13:48:29
//     */
//    public void getV3PlatFormNumber(String openId,String description, String outTradeNo, Double amount, Double goodsTag, String userIp) throws Exception {
//        ValidateUtil.validateStringField(description, description);
//        ValidateUtil.validateStringField(outTradeNo, "outTradeNo");
//        ValidateUtil.validateNonNegative(amount, "amount");
//        ValidateUtil.validateStringField(userIp, "userIp");
//
//        Map<String, Object> body = new HashMap<>();
//        body.put("appid", WechatPayConfig.APP_ID); //appID
//        body.put("mchid", WechatPayConfig.Mch_ID); //商户号
//        body.put("description", description); //商品描述
//        body.put("out_trade_no", outTradeNo); //订单号
//        body.put("time_expire", calculateExpireTime()); //最后支付时间  标准格式：yyyy-MM-DDTHH:mm:ss+TIMEZONE
//        body.put("notify_url", WechatPayConfig.APP_URL); //支付成功回调地址
//        body.put("goods_tag", goodsTag); //优惠券
//        Map<String, Object> amounts = new HashMap<>();
//        amounts.put("total", 100);
//        body.put("amount", amounts); //金额信息 订单总金额，单位为分，整型
//
//        Map<String, Object> scene_info = new HashMap<>();
//        scene_info.put("payer_client_ip", userIp);
//        body.put("scene_info", scene_info);
//
//        Map<String, String> user = new HashMap<>();
//        user.put("openid", openId);
//        body.put("payer", user);
//
//        IJPayHttpResponse response = WxPayApi.v3(
//            RequestMethodEnum.POST,
//            WxDomainEnum.CHINA.toString(),
//            BasePayApiEnum.APP_PAY.toString(),
//            WechatPayConfig.Mch_ID,
//            getSerialNumber(),
//            null,
//            WechatPayConfig.certPath,
//            JSONUtil.toJsonStr(body)
//            );
//
//        String serialNumber = response.getHeader("Wechatpay-Serial");
//        String resultBody = response.getBody();
//        int status = response.getStatus();
//        log.info("serialNumber: {}", serialNumber);
//        log.info("status: {}", status);
//        log.info("body: {}", resultBody);
//        int isOk = 200;
//        if (status == isOk) {
//            JSONObject jsonObject = JSONUtil.parseObj(body);
//            JSONArray dataArray = jsonObject.getJSONArray("data");
//            // 默认认为只有一个平台证书
//            JSONObject encryptObject = dataArray.getJSONObject(0);
//            JSONObject encryptCertificate = encryptObject.getJSONObject("encrypt_certificate");
//            String associatedData = encryptCertificate.getStr("associated_data");
//            String cipherText = encryptCertificate.getStr("ciphertext");
//            String nonce = encryptCertificate.getStr("nonce");
//            String serialNo = encryptObject.getStr("serial_no");
//            String platSerialNo = this.savePlatformCert(associatedData, nonce, cipherText);
//            log.info("平台证书序列号: {} serialNo: {}", platSerialNo, serialNo);
//        }
//        boolean verifySignature = WxPayKit.verifySignature(response, WechatPayConfig.platformCertPath);
//        log.info("verifySignature:" + verifySignature);
//    }

//    }

//    /**
//     * 功能描述:获取平台证书，自动更新
//     * 注意：这个方法内置了平台证书的获取和返回值解密
//     */
//    public static Verifier getVerifiers(String mchSerialNo) {
//        Verifier verifier = null;
//        if (verifierMaps.isEmpty() || !verifierMaps.containsKey(mchSerialNo)) {
//            verifierMaps.clear();
//            try {
//                PrivateKey privateKey = getPrivateKey();
//                //刷新
//                PrivateKeySigner signer = new PrivateKeySigner(mchSerialNo, privateKey);
//                WechatPay2Credentials credentials = new WechatPay2Credentials(WxV3PayConfig.Mch_ID, signer);
//                verifier = new AutoUpdateCertificatesVerifier(credentials
//                    , apiV3Key.getBytes("utf-8"));
//                verifierMaps.put(verifier.getValidCertificate().getSerialNumber()+"", verifier);
//            } catch (UnsupportedEncodingException e) {
//                e.printStackTrace();
//            } catch (IOException e) {
//                throw new RuntimeException(e);
//            }
//        } else {
//            verifier = verifierMaps.get(mchSerialNo);
//        }
//        return verifier;
//    }


//    private String savePlatformCert(String associatedData, String nonce, String cipherText) {
//        try {
//            AesUtil aesUtil = new AesUtil(WechatPayConfig.apiV3Key.getBytes(StandardCharsets.UTF_8));
//            // 平台证书密文解密
//            String publicKey = aesUtil.decryptToString(
//                associatedData.getBytes(StandardCharsets.UTF_8),
//                nonce.getBytes(StandardCharsets.UTF_8),
//                cipherText
//            );
//            // 保存证书
//            log.info("获取证书key：{},保存路径platformCert:{}", publicKey, WechatPayConfig.platformCertPath);
//            //将生成的证书写入指定路径，文件名为：cert.pem
//            FileOutputStream fos = new FileOutputStream(WechatPayConfig.platformCertPath);
//            fos.write(publicKey.getBytes());
//            fos.close();
//            // 获取平台证书序列号
//            X509Certificate certificate = PayKit.getCertificate(new ByteArrayInputStream(publicKey.getBytes()));
//            return certificate.getSerialNumber().toString(16).toUpperCase();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return null;
//    }


    /**
     * 计算支付超时时间（当前时间 + 30分钟）
     * @Author 王晨沣 2307105054
     * @Date 2025-05-27 14:01:27
     */
    public static String calculateExpireTime() {
        LocalDateTime expireTime = LocalDateTime.now().plusMinutes(WechatPayConfig.FINAL_TIME);
        return expireTime.format(DateTimeFormatter.ofPattern("yyyy-MM-DDTHH:mm:ssXXX"));
    }


}
